import {Directive, Input, OnInit} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {Tree} from "primeng/tree";
import {ErrorService} from "../api/ErrorService";
import {TreeNode} from "primeng/api";
import {Observable, Subject} from "rxjs";

@Directive({
  selector: '[gnTree]',
})
export class TreeDirective implements OnInit {

  @Input() url: string;
  @Input() rootLabel: string;
  @Input() rootData: any = {id: null, name: this.rootLabel};
  @Input() labelField: string = 'name';
  @Input() keyField: string = 'id';
  @Input() autoSelectNode = true;
  @Input() autoExpandLevel = 1;

  constructor(private httpClient: HttpClient,
              private errorService: ErrorService,
              private tree: Tree) {

    this.tree.onNodeExpand.subscribe(event => {
      if (!event.node.leaf && !event.node.children) {
        this.loadData(event);
      }
    });

  }

  private loadData(event): Observable<TreeNode[]> {
    const observer = new Subject<TreeNode[]>();

    if (event.node) {
      this.tree.loading = true;
      const id = event.node.data[this.keyField] === null ? '' : event.node.data[this.keyField];
      this.httpClient.get(this.url + id).subscribe((value: any[]) => {
          event.node.children = value.map(v => {
            return {
              "label": v[this.labelField],
              "data": v,
              "leaf": false
            };
          });
          this.tree.loading = false;
          if (value.length === 0) {
            event.node.leaf = true;
          }
          observer.next(event.node.children);
        },
        error => {
          this.tree.loading = false;
          this.errorService.occur({message: '获取数据错误', error: error});
        });
    }
    return observer;
  }

  ngOnInit(): void {
    this.reload();
  }

  private selectAndExpand(): void {
    if (this.tree.value.length > 0) {
      if (this.autoSelectNode === true) {
        this.tree.selection = [this.tree.value[0]];
        this.tree.selectionChange.emit(this.tree.selection);
      }
      this.expandNode(this.tree.value, this.autoExpandLevel);
    }
  }

  private expandNode(nodes: TreeNode[], deep: number): void {
    if (nodes && deep > 0) {
      nodes.forEach(node => {
        node.expanded = true;
        this.loadData({node: node}).subscribe(() => {
          this.expandNode(nodes[0].children, deep - 1);
        });
      });
    }
  }

  public reload(): void {
    const rootNode = [{
      'label': this.rootLabel,
      'data': this.rootData,
      'leaf': false
    }];
    this.tree.value = rootNode;
    if (!this.rootLabel) {
      this.loadData({'node': this.tree.value[0]})
        .subscribe(() => {
          this.tree.value = this.tree.value[0].children;
          this.selectAndExpand();
        });
    } else {
      this.selectAndExpand();
    }
  }

  public reloadCurrent(): void {
    if (this.tree.selection && this.tree.selection.length > 0) {
      this.tree.selection[0].leaf = false;
      this.tree.selection[0].children = null;
      this.tree.onNodeExpand.emit({node: this.tree.selection[0]});
    }
  }

}
